/* Only some PIT operations such as load init counter need a hypervisor hook.
- * leave many other operations in user space DM
+ * leave all other operations in user space DM
*/
void vmx_hooks_assist(struct exec_domain *d)
{
struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit);
int rw_mode;
- if (p->state == STATE_IORESP_HOOK) { /*load init count*/
- vpit->init_val = (p->u.data & 0xFFFF) ; /* frequency(ms) of pit */
- vpit->period = (vpit->init_val) * 1000 / PIT_FREQ; /* frequency(ms) of pit */
+ /* load init count*/
+ if (p->state == STATE_IORESP_HOOK) {
+ /* init count for this channel */
+ vpit->init_val = (p->u.data & 0xFFFF) ;
+ /* frequency(ms) of pit */
+ vpit->period = DIV_ROUND(((vpit->init_val) * 1000), PIT_FREQ);
+ if (vpit->period < 1) {
+ printk("VMX_PIT: guest programmed too small an init_val: %lx\n",
+ vpit->init_val);
+ vpit->period = 1;
+ }
vpit->vector = ((p->u.data >> 16) & 0xFF);
vpit->channel = ((p->u.data >> 24) & 0x3);
+ vpit->first_injected = 0;
vpit->count_LSB_latched = 0;
vpit->count_MSB_latched = 0;
else
clear_highest_bit(d, highest_vector);
+ /* close the window between guest PIT initialization and sti */
+ if (highest_vector == vpit->vector && !vpit->first_injected){
+ vpit->first_injected = 1;
+ vpit->pending_intr_nr = 0;
+ }
+
intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector);
__vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
-
#ifndef _VMX_VIRPIT_H
#define _VMX_VIRPIT_H
#include <xen/config.h>
unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
unsigned long long inject_point; /* the time inject virt intr */
struct ac_timer pit_timer; /* periodic timer for mode 2*/
+ int first_injected; /* flag to prevent shadow window */
/* virtual PIT state for handle related I/O */
int read_state;
extern void vmx_hooks_assist(struct exec_domain *d);
#endif /* _VMX_VIRPIT_H_ */
-
-#ifndef _VMX_VIRPIT_H
-#define _VMX_VIRPIT_H
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/time.h>
-#include <xen/errno.h>
-#include <xen/ac_timer.h>
-#include <asm/vmx_vmcs.h>
-
-#define PIT_FREQ 1193181
-
-#define LSByte 0
-#define MSByte 1
-#define LSByte_multiple 2
-#define MSByte_multiple 3
-
-struct vmx_virpit_t {
- /* for simulation of counter 0 in mode 2*/
- int vector; /* the pit irq vector */
- unsigned int period; /* the frequency. e.g. 10ms*/
- unsigned int channel; /* the pit channel, counter 0~2 */
- unsigned long *intr_bitmap;
- unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
- unsigned long long inject_point; /* the time inject virt intr */
- struct ac_timer pit_timer; /* periodic timer for mode 2*/
-
- /* virtual PIT state for handle related I/O */
- int read_state;
- int count_LSB_latched;
- int count_MSB_latched;
-
- unsigned int count; /* the 16 bit channel count */
- unsigned int init_val; /* the init value for the counter */
-
-} ;
-
-#endif /* _VMX_VIRPIT_H_ */
#define SWAP(_a, _b) \
do { typeof(_a) _t = (_a); (_a) = (_b); (_b) = _t; } while ( 0 )
+#define DIV_ROUND(x, y) (((x) + (y) - 1) / (y))
+
#define reserve_bootmem(_p,_l) ((void)0)
struct domain;